package ev.ftw.dna;

import ev.ftw.gff.FragConocido;

/**
 * Clase que define los hilos de trabajo paralelo con los cromosomas.
 * 
 * @date 01.08.2012
 * @author Enrique Vázquez de Luis
 *
 */
public class HiloExp extends Thread{
	
	/*
	 * Posibles operaciones que realiza el hilo.
	 */
	public final static int BANDWITH = 1;
	public final static int REDUCE_RESOLUCION = 2;
	public final static int AUMENTA_RESOLUCION = 3;
	public final static int ELIMINA_ERRORES = 4;
	public final static int FILTRO_WAVELET = 5;
	public final static int SUMA = 6;
	public final static int RESTA = 7;
	public final static int MULTIPLICA = 8;
	public final static int DIVIDE = 9;
	public final static int BUSCA_EXPRESION_MEDIA = 10;
	public final static int BUSCA_EXPRESION_WLT = 11;
	public final static int SUMA_NUMERO = 12;
	public final static int RESTA_NUMERO = 13;
	public final static int MULTIPLICA_NUMERO = 14;
	public final static int DIVIDE_NUMERO = 15;
	
	Cromosoma c; // Cromosoma de trabajo.
	Cromosoma operando2; // Cromosoma para operar con él, si fuera necesario.
	FragConocido [] fragmentos; // Fragmentos encontrados.
	int operacion; // Operación a realizar.
	int arg0; // Argumento entero para las operaciones que lo requieran.
	float limiteWLT, limiteMedia; // Argumentos decimales para las operaciones que lo requieran.
	
	/**
	 * Getter de la operación.
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 * @return La operación a realizar por el hilo.
	 */
	public int getOperacion() {
		return operacion;
	}

	/**
	 * Getter del argumento entero.
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 * @return El argumento entero.
	 */
	public int getArg0() {
		return arg0;
	}


	/**
	 * Setter del argumento entero. Solo acepta número positivos.
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 * @param arg0 El nuevo argumento entero.
	 */
	public void setArg0(int arg0) {
		if(arg0 < 0) this.arg0 = 0;
		else this.arg0 = arg0;
	}

	/**
	 * Getter del límite del salto de la Wavelet.
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 * @return El límite del salto de la Wavelet.
	 */
	public float getLimiteWLT() {
		return limiteWLT;
	}

	/**
	 * Setter del límite de salto de la Wavelet. Coge el valor absoluto del número pasado como argumento.
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 * @param limiteWLT El nuevo límite de salto de la wavelet.
	 */
	public void setLimiteWLT(float limiteWLT) {
		if(limiteWLT < 0) this.limiteWLT = -limiteWLT;
		else this.limiteWLT = limiteWLT;
	}

	/**
	 * Getter del valor límite de la media.
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 * @return Valor límite de la media.
	 */
	public float getLimiteMedia() {
		return limiteMedia;
	}

	/**
	 * Setter del valor límite de la media.
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 * @param limiteMedia Nuevo límite de la media.
	 */
	public void setLimiteMedia(float limiteMedia) {
		this.limiteMedia = limiteMedia;
	}
	
	/**
	 * Getter de los fragmentos encontrados.
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 * @return Los fragmentos encontrados.
	 */
	public FragConocido[] getFragmentos() {
		return fragmentos;
	}

	/**
	 * Contructor del Hilo.
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 * @param c Cromosoma sobre el que operar.
	 * @param operacion Operación a realizar.
	 */
	public HiloExp(Cromosoma c, int operacion){
		this.c = c;
		this.operacion = operacion;
		this.operando2 = null;
	}
	
	/**
	 * Constructor del Hilo.
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 * @param operando1 Cromosoma sobre el que operar.
	 * @param operando2 Cromosoma que operar con el anterior.
	 * @param operacion Operación a realizar.
	 */
	public HiloExp(Cromosoma operando1, Cromosoma operando2, int operacion){
		this.c = operando1;
		this.operacion = operacion;
		this.operando2 = operando2;
		
	}
	
	/**
	 * Función para configurar la operación a realizar, se le pasan los 3 parámetros simultáneamente.
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 * @param arg0 Parametro entero.
	 * @param limiteWLT Límite de salto Wavelet.
	 * @param limiteMedia Límite de la media.
	 */
	public void configuraOperacion(int arg0, float limiteWLT, float limiteMedia){
		this.arg0 = arg0;
		this.limiteWLT = limiteWLT;
		this.limiteMedia = limiteMedia;
	}
	
	/**
	 * Función principal del hilo.<br>
	 * Elige la acción a realizar por medio de la "operacion".
	 * 
	 * @date 01.08.2012
	 * @author Enrique Vázquez de Luis
	 */
	public void run(){
		
		switch(this.operacion){
			case BANDWITH:
				c.bandwith(arg0);
				break;
			case REDUCE_RESOLUCION:
				c.reduceResolucion(arg0);
				break;
			case AUMENTA_RESOLUCION:
				c.aumentaResolucion(arg0);
				break;
			case ELIMINA_ERRORES:
				c.eliminaErroneos(arg0);
				break;
			case FILTRO_WAVELET:
				c.filtroWLT(limiteWLT);
				break;
			case SUMA:
				c.suma(this.operando2);
				break;
			case RESTA:
				c.resta(this.operando2);
				break;
			case MULTIPLICA:
				c.multiplica(this.operando2);
				break;
			case DIVIDE:
				c.divide(this.operando2);
				break;
			case BUSCA_EXPRESION_MEDIA:
				this.fragmentos = c.buscaExpresionSencillo(limiteMedia);
				break;
			case BUSCA_EXPRESION_WLT:
				int res = c.getResolucion();
				c.aumentaResolucion(res);
				this.fragmentos = c.buscaExpresionWLT(limiteWLT, limiteMedia);
				c.reduceResolucion(res);
				break;
			case SUMA_NUMERO:
				c.sumaNumero(this.limiteMedia);
				break;
			case RESTA_NUMERO:
				c.restaNumero(this.limiteMedia);
				break;
			case MULTIPLICA_NUMERO:
				c.multiplicaNumero(this.limiteMedia);
				break;
			case DIVIDE_NUMERO:
				c.divideNumero(this.limiteMedia);
				break;
		}
		
	}
}